package tools.streamtools;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Spliterator;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import static java.util.Objects.isNull;
import static java.util.Spliterators.spliteratorUnknownSize;

public class NullableStream {
    public static <T> Stream<T> of(List<T> list) {
        return list == null ? Stream.of() : list.stream();
    }

    public static <T> Stream<T> of(T[] array) {
        return array == null ? Stream.of() : Stream.of(array);
    }

    public static <T> Stream<T> of(Iterable<T> iterable) {
        return isNull(iterable)
            ? Stream.of()
            : StreamSupport.stream(iterable.spliterator(), false);
    }

    public static <T> Stream<T> of(Iterator<T> iterator) {
        return isNull(iterator)
            ? Stream.of()
            : StreamSupport.stream(spliteratorUnknownSize(iterator, Spliterator.ORDERED), false);
    }

    public static <K, V> Stream<Map.Entry<K, V>> of(Map<K, V> map) {
        return isNull(map)
            ? Stream.of()
            : of(map.entrySet());
    }

    public static <T, R> List<R> mapList(List<T> list, Function<T, R> function) {
        return of(list)
            .map(function)
            .collect(Collectors.toList());
    }

    public static <T, R> List<R> mapList(T[] array, Function<T, R> function) {
        return of(array)
            .map(function)
            .collect(Collectors.toList());
    }


}
